/*
 * Copyright (c) 2017, MegaEase
 * All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package util

import (
	"encoding/json"

	"github.com/megaease/easemeshctl/cmd/client/resource"
	"github.com/megaease/easemeshctl/cmd/client/resource/meta"
	"github.com/megaease/easemeshctl/cmd/client/valid"

	"github.com/pkg/errors"
)

// Decoder decodes bytes stream to a MeshObject
type Decoder interface {
	Decode(data []byte) (meta.MeshObject, *meta.VersionKind, error)
}

type decoder struct {
	oc resource.ObjectCreator
}

func (d *decoder) Decode(jsonBuff []byte) (meta.MeshObject, *meta.VersionKind, error) {
	vk := &meta.VersionKind{}
	err := json.Unmarshal(jsonBuff, vk)
	if err != nil {
		return nil, nil, errors.Wrap(err, "unmarshal data to resource.VersionKind failed")
	}

	meshObject, err := d.oc.NewFromKind(*vk)
	if err != nil {
		return nil, vk, err
	}

	err = json.Unmarshal(jsonBuff, meshObject)
	if err != nil {
		return nil, vk, errors.Wrap(err, "unmarshal data to MeshObject")
	}

	vr := valid.Validate(meshObject)
	if !vr.Valid() {
		return nil, nil, vr
	}

	return meshObject, vk, nil
}

func newDefaultDecoder() Decoder {
	return &decoder{oc: resource.NewObjectCreator()}
}
